/**
 * prefs.js
 * Copyright (C) 2007-2011 Tommi Rautava
 * 
 * This file is part of Popmungo.
 *
 * Popmungo is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Popmungo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

org.mozdev.popmungo.prefs = {
	
	prefTypeNames: {	
		0: "PREF_INVALID",
		32: "PREF_STRING",
		64: "PREF_INT",
		128: "PREF_BOOL"
	},
	
	/**
	 * Preference objects.
	 */
	_pref: Components.classes["@mozilla.org/preferences-service;1"].
		getService(Components.interfaces.nsIPrefService).
		QueryInterface(Components.interfaces.nsIPrefBranch2),

	/**
	 * Add Popmungo preference observer.
	 */
	addObserver: function addObserver(aDomain, aObserver) {
		org.mozdev.popmungo.logger.debug('observer='+ aObserver +', pref='+ aDomain);
		this._pref.QueryInterface(Components.interfaces.nsIPrefBranch2);
		this._pref.addObserver(aDomain, aObserver, false);
	},

	/**
	 * Remove Popmungo preference observer.
	 */
	removeObserver: function removeObserver(aDomain, aObserver) {
		org.mozdev.popmungo.logger.debug('observer='+ aObserver +', pref='+ aDomain);
		this._pref.removeObserver(aDomain, aObserver);
	},

	/**
	 * Is preference set?
	 * 
	 * @param aPrefName
	 */
	exists: function exists(aPrefName) 
	{
		return this._pref.getPrefType(aPrefName) != 0;
	},

	
	isInvalidPrefType: 
	function isInvalidPrefType(prefTypeString, prefTypeNumber) 
	{
		switch (prefTypeNumber) {
			case this._pref.PREF_STRING:
				return (prefTypeString != "string");
				
			case this._pref.PREF_BOOL:
				return (prefTypeString != "boolean");
				
			case this._pref.PREF_INT:
				return (prefTypeString != "number");
				
			case this._pref.PREF_INVALID: 
				return false;
		}
		
		return false;
	},

	/**
	 * Get preference value.
	 * 
	 * @param aPrefName
	 * @param aDefaultValue
	 */
	getPref: function getPref(aPrefName, aDefaultValue) 
	{
		if (!aPrefName) {
			throw "getPref() called without a preference name.";
		}
		
		var value;
		var prefType;

		try {
			prefType = this._pref.getPrefType(aPrefName);
	
			switch (prefType) {
				case this._pref.PREF_BOOL:
					value = this._pref.getBoolPref(aPrefName);
					break;
				
				case this._pref.PREF_INT:
					value = this._pref.getIntPref(aPrefName);
					break;
				
				case this._pref.PREF_STRING:
					value = this._pref.getComplexValue(aPrefName,
						Components.interfaces.nsISupportsString).data;
					break;
				
				case this._pref.PREF_INVALID: 
					// Return default value if the preference is not set.
					value = this._getDefaultPref(aPrefName, aDefaultValue);
					org.mozdev.popmungo.logger.debug('Invalid pref: '+ aPrefName +'='+ prefType);
					break;
					
				default:
					value = this._getDefaultPref(aPrefName, aDefaultValue);
					org.mozdev.popmungo.logger.logError('Invalid pref type: '+ aPrefName +'='+ prefType);
			}
			
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
			value = this._getDefaultPref(aPrefName, aDefaultValue);
		}
		
		org.mozdev.popmungo.logger.debug(aPrefName +'['+ this.prefTypeNames[prefType] +']='+	value);

		return value;
	},
	
	
	_getDefaultPref: function _getDefaultPref(aPrefName, aDefaultValue) {
		if (!aDefaultValue && aDefaultValue != 0) {
			return org.mozdev.popmungo.defaultPrefs[aPrefName];
		}

		return aDefaultValue;
	},
	
	
	/**
	 * Set preference value.
	 * 
	 * @param aPrefName
	 * @param aValue
	 */
	setPref: function setPref(aPrefName, aValue) 
	{
		if (!aPrefName) {
			throw "setPref() called without a preference name.";
		}

		try {
			var prefType = typeof(aValue);
			var prefType2 = this._pref.getPrefType(aPrefName);
			
			org.mozdev.popmungo.logger.debug(aPrefName +'['+ prefType +']='+ aValue);
			
			if (this.isInvalidPrefType(prefType, prefType2)) {
				org.mozdev.popmungo.logger.logError(aPrefName +'['+ prefType2 +'] is to be replaced by '+
					aPrefName +'['+ prefType +']');
	
				this._pref.remove(aPrefName);
			}
	
			switch (prefType) {
				case "string":
					var str = Components.classes["@mozilla.org/supports-string;1"]
						.createInstance(Components.interfaces.nsISupportsString);
					str.data = aValue;
					this._pref.setComplexValue(aPrefName, 
						Components.interfaces.nsISupportsString, str);
					break;
					
				case "boolean": 
					this._pref.setBoolPref(aPrefName, aValue); 
					break;
					
				case "number": 
					this._pref.setIntPref(aPrefName, aValue); 
					break;
					
				default:
					org.mozdev.popmungo.logger.logError('Unsupported type for '+ aPrefName +': '+ prefType);				
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
	},


	/**
	 * Get language related preference.
	 * 
	 * @param langId
	 * @param aPrefName
	 * @param aDefaultValue
	 */
	getLanguagePref: 
	function getLanguagePref(langId, aPrefName, aDefaultValue) 
	{
		var prefName = aPrefName.replace('<n>', langId);
		return this.getPref(prefName, aDefaultValue);
	},
	

	/**
	 * Set language related preference.
	 * 
	 * @param langId
	 * @param aPrefName
	 * @param aValue
	 */
	setLanguagePref: 
	function setLanguagePref(langId, aPrefName, aValue) 
	{		
		if ((langId != undefined) && (aPrefName != undefined)) {
			var prefName = aPrefName.replace('<n>', langId);
			this.setPref(prefName, aValue);
		} else {
			org.mozdev.popmungo.logger.logError('Language ID or pref is undefined:\n'+
				'lang ID='+ langId +', pref='+ aPrefName +', value='+ aValue);		
		}
	},
	
	/**
	 * Get value of character/user specific preference.
	 * 
	 * @param characterId
	 * @param aPrefName
	 * @param aDefaultValue
	 */
	getCharacterPref: 
	function getCharacterPref(characterId, aPrefName, aDefaultValue) 
	{
		if (characterId && aPrefName) {
			var prefName = aPrefName.replace('<n>', characterId);
			
			return this.getPref(prefName, aDefaultValue);
		}

		org.mozdev.popmungo.logger.logError('char ID or pref is undefined:\n'+
			'char ID='+ characterId +', pref='+ aPrefName +', default='+ aDefaultValue);
		
		return null;
	},
	

	/**
	 * Set value of character/user specific preference.
	 * 
	 * @param characterId
	 * @param aPrefName
	 * @param aValue
	 */
	setCharacterPref: 
	function setCharacterPref(characterId, aPrefName, aValue) 
	{		
		if (characterId && aPrefName) {
			var prefName = aPrefName.replace('<n>', characterId);
			this.setPref(prefName, aValue);
		} else {
			org.mozdev.popmungo.logger.logError('char ID or pref is undefined:\n'+
				'char ID='+ characterId +', pref='+ aPrefName +', value='+ aValue);
		}
	},
	
	/**
	 * Delete preference branch.
	 * 
	 * @param aPrefName
	 */
	deleteBranch: function deleteBranch(aPrefName) {
		this._pref.deleteBranch(aPrefName);
	},
	
	/**
	 * Is setting enabled?
	 * 
	 * @param aPrefName
	 * @param aDefaultValue
	 */
	isEnabled: function isEnabled(aPrefName) {
		return org.mozdev.popmungo.prefs.getPref(aPrefName, false);
	},
	

	getTimestamp: function getTimestamp(aPrefName) {
		var ts = org.mozdev.popmungo.prefs.getPref(aPrefName, 0);
		var d = new Date();
		d.setTime(parseInt(ts));
		return d;
	}, 

	
	setTimestamp: function setTimestamp(aPrefName) {
		var d = new Date();
		org.mozdev.popmungo.prefs.setPref(aPrefName, d.getTime() +'');
	},
	
	
	/**
	 * aBranchName The base branch. Must have a trailing '.' (dot).
	 */
	getChildList: function getChildList(aBranchName) {
		var branch = Components.classes["@mozilla.org/preferences-service;1"].
			getService(Components.interfaces.nsIPrefService).
			getBranch(this._pref.root + aBranchName);
		
		return branch.getChildList("", {});
	},
	
	
	prefHasUserValue: function prefHasUserValue(aPrefName) {
		return this._pref.prefHasUserValue(aPrefName);
	},
	
	
	clearUserPref: function clearUserPref(aPrefName) {
		this._pref.clearUserPref(aPrefName);
	}
};
